package com.example.demo.service;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;

import com.example.demo.model.FileUploadCompleteData;
import com.example.demo.util.FileIO;

@Service
public class FileStorageService {

	/**
	 * 文件根路径
	 */
	private static String STORAGE_ROOT = "file-storage";

	/**
	 * 文件切片前缀
	 */
	private static String CHUNK_PREFIX = "chunk_";

	/**
	 * 缓冲区大小
	 */
	private int bufferSize = 1024 * 1024 * 5;

	/**
	 * 创建文件储存
	 */
	public boolean createFileStorage(String sessionID) {
		Path path = Paths.get(STORAGE_ROOT, sessionID);
		try {
			if (Files.exists(path))
				return false;
			Files.createDirectories(path);
		} catch (IOException e) {
			System.err.println(e);
			return false;
		}
		return true;
	}

	/**
	 * 储存切片
	 */
	public boolean storeChunk(String sessionID, String chunkIndex, byte[] data) {
		Path chunkPath = Paths.get(STORAGE_ROOT, sessionID, CHUNK_PREFIX + chunkIndex);
		if (Files.exists(chunkPath)) {
			// 切片重复则将之删除
			try {
				FileIO.deleteFolder(chunkPath);
			} catch (IOException e) {
				System.err.println(e);
			}
		}
		try (FileOutputStream fos = new FileOutputStream(chunkPath.toFile());
				BufferedOutputStream out = new BufferedOutputStream(fos, bufferSize)) {
			out.write(data);
		} catch (IOException e) {
			System.err.println(e);
			return false;
		}
		return true;
	}

	/**
	 * 合并切片
	 */
	public boolean assembleFile(String sessionID, String name, String suffix) {
		String fileName = sessionID + suffix;
		Path directoryPath = Paths.get(STORAGE_ROOT, sessionID);
		Path filePath = Paths.get(STORAGE_ROOT);
		Path outputPath = filePath.resolve(fileName);
		try (FileOutputStream fos = new FileOutputStream(outputPath.toFile());
				FileChannel outChannel = fos.getChannel()) {

			List<Path> chunkPaths = Files.list(directoryPath)
					.filter(path -> path.getFileName().toString().startsWith(CHUNK_PREFIX))
					.sorted(Comparator.comparingInt(
							path -> Integer.parseInt(path.getFileName().toString().replace(CHUNK_PREFIX, ""))))
					.collect(Collectors.toList());

			for (Path chunk : chunkPaths) {
				try (FileChannel chunkChannel = FileChannel.open(chunk)) {
					chunkChannel.transferTo(0, chunkChannel.size(), outChannel);
				}
			}

			FileIO.deleteFolder(directoryPath);

		} catch (IOException e) {
			System.out.printf("Error assembling file: {}", e.getMessage());
			return false;
		}
		return true;

	}

	/**
	 * 文件注册
	 */
	public void registerFile(FileUploadCompleteData metaData) {

	}

	/**
	 * 删除IO错误的切片
	 */
	public void deleteChunk(String sessionID, String chunkIndex) {
		Path chunkPath = Paths.get(STORAGE_ROOT, sessionID, CHUNK_PREFIX + chunkIndex);
		try {
			FileIO.deleteFolder(chunkPath);
		} catch (IOException e) {
			System.err.println(e);
		}
	}

	/**
	 * 删除会话文件
	 */
	public void deleteSession(String sessionID) {
		Path chunkPath = Paths.get(STORAGE_ROOT, sessionID);
		try {
			FileIO.deleteFolder(chunkPath);
		} catch (IOException e) {
			System.err.println(e);
		}
	}

}